package System;

import Controller.ChatController;
import Controller.Exceptions.ControllerPerformException;
import GUI.AboutDialog;
import GUI.ChatGUI;
import Type.AudioSound;
import Network.ChatNetwork;
import Network.Exceptions.NetworkException;
import System.Exception.SystemException;

import UDPTools.Settings.UDPSettings;
import java.awt.event.KeyEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
/**
 * La classe ChatSystem est l'interface graphique principale de notre application.
 * Elle permet à un utilisateur de se loguer.
 * 
 * @author      Frank Djomo
 * @author      Christelle SIAGO HAPPI
 * @author      djomopoueme@gmail.com
 * @author      christelle.siagohappi@gmail.com
 * @version     1.0
 */

public class ChatSystem extends javax.swing.JFrame  {

    private  ChatController mCtrl;
    private  ChatNetwork   mNI;
    private  ChatGUI   mGUI;
    private  int portEcoute,portDistant,portEnvoi;
    private  boolean isLaunch;
    /**
    * Constructeur
    * @param portEcoute             Port d'ecoute du system
    * @param portEcouteDistant      Port d'ecoute des systemes distants
    * @param portEnvoi              Port d'envoi des messages
    */
    public ChatSystem(int portEcoute , int portEcouteDistant,int portEnvoi) throws SystemException {

        initComponents();
        this.setVisible(true);
        this.setSize(450,700);
        this.setPorts(portEcoute, portEcouteDistant, portEnvoi);
        isLaunch=false;
    }
    /**
    * Constructeur
    */
    public ChatSystem() throws SystemException {
        this(UDPSettings.UDP_PORT_ECOUTE, UDPSettings.UDP_PORT_ECOUTE, UDPSettings.UDP_PORT_ENVOI);
    }
   
    private void setPorts(int portEcoute,int portDistant, int portEnvoi) throws SystemException {
        if(portEcoute < UDPSettings.UDP_PORT_MIN || portEcoute > UDPSettings.UDP_PORT_MAX)
            throw new SystemException("Numéro port invalide");
        if(portDistant < UDPSettings.UDP_PORT_MIN || portDistant > UDPSettings.UDP_PORT_MAX)
            throw new SystemException("Numéro port invalide");
        if(portEcoute < UDPSettings.UDP_PORT_MIN || portEcoute > UDPSettings.UDP_PORT_MAX)
            throw new SystemException("Numéro port invalide");

        this.portEcoute = portEcoute;
        this.portDistant=portDistant;
        this.portEnvoi = portEnvoi;
    }

    /**
    * Initialise cette ChatSys avec les ports à utiliser
    * @param portEcoute Port local
    * @param portDistant Port distant
    */
    private void initialize() throws SystemException{
        try {
            this.mGUI = new ChatGUI();
            this.mCtrl = new ChatController();
            this.mNI =new ChatNetwork(portEcoute, portDistant, portEnvoi);


            this.mCtrl.setGUI(mGUI);                 
            this.mCtrl.setNI(mNI);

            this.mNI.setController(mCtrl);

            this.mGUI.setController(mCtrl);
            this.mGUI.setChatSys(this);


        } catch (NetworkException ex) {
            Logger.getLogger(ChatSystem.class.getName()).log(Level.SEVERE, null, ex);
            JOptionPane.showMessageDialog(this,"Impossible de lancer le JChat","Erreur",JOptionPane.ERROR_MESSAGE);
            throw new SystemException("Erreur lors du lancement du ChatSystem", ex);
        }
    }


    /**
    * Gère la connexion de l'utilisateur local
    */
    private  void connexion()
    {
       //Gestion de la connexion
        if(!logField.getText().equals("")){
            try{    
                AudioSound con= new AudioSound(ChatSystem.class.getResource("/Ressources/sons/connect.wav"));
                new Thread(con).start();    

                if(!isLaunch) this.initialize();

                connectButton.setEnabled(false);
                this.mGUI.setVisible(true);
                this.setVisible(false);
                this.mGUI.performConnect(toUpperCase(logField.getText()));
                this.mGUI.setWelcome();
                isLaunch=true;
            }  
            catch (ControllerPerformException ex) {
                Logger.getLogger(ChatSystem.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(this,"Une erreur est survenue","Connexion",JOptionPane.ERROR_MESSAGE);

            } catch (SystemException ex) {
                Logger.getLogger(ChatSystem.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(this,"Une erreur est survenue","Connexion",JOptionPane.ERROR_MESSAGE);
            }                
        }
        else{
            JOptionPane.showMessageDialog(this,"Veuillez saisir un login","Saisie nulle",JOptionPane.ERROR_MESSAGE);
        }
    }
    /**
    * Gère la déconnexion de l'utilisateur local
    */
    public void deconnexion(){
        //Son de deconnexion
        
        AudioSound dis= new AudioSound(ChatSystem.class.getResource("/Ressources/sons/disconnect.wav"));
        new Thread(dis).start();
        connectButton.setEnabled(true);      
        this.mGUI.setVisible(false);
        this.setVisible(true);    
    }
    /**
    * Met le premier caractères en majuscules
    * @param rUser chaine à mettre en majuscule
    */
    private String toUpperCase(String rUser)
    {
        char[] temp = rUser.toUpperCase().toCharArray();
        StringBuilder tampon = new StringBuilder(rUser);
        tampon.setCharAt(0,temp[0]);
        return tampon.toString();
    }

    /** This method is called from within the constructor to
    * initialize the form.
    * WARNING: Do NOT modify this code. The content of this method is
    * always regenerated by the Form Editor.
    */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        connectButton = new javax.swing.JButton();
        labelLogin = new javax.swing.JLabel();
        logField = new javax.swing.JTextField();
        barreEtat = new javax.swing.JLabel();
        labelConnexion = new javax.swing.JLabel();
        menuBar = new javax.swing.JMenuBar();
        menuFichier = new javax.swing.JMenu();
        itemConnexion = new javax.swing.JMenuItem();
        itemDeconnexion = new javax.swing.JMenuItem();
        menuHelp = new javax.swing.JMenu();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("JChat");
        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        setIconImage(new javax.swing.ImageIcon(getClass().getResource("/Ressources/images/app.png")).getImage()
        );
        setResizable(false);

        connectButton.setFont(new java.awt.Font("Tahoma", 2, 11));
        connectButton.setForeground(new java.awt.Color(0, 153, 255));
        connectButton.setText("Se connecter");
        connectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectButtonActionPerformed(evt);
            }
        });

        labelLogin.setFont(new java.awt.Font("Cambria", 1, 14));
        labelLogin.setForeground(new java.awt.Color(0, 153, 204));
        labelLogin.setText("          Login");

        logField.setToolTipText("Entrer votre login");
        logField.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        logField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                logFieldKeyPressed(evt);
            }
        });

        barreEtat.setFont(new java.awt.Font("Cambria", 0, 12));
        barreEtat.setText("Déconnecté");
        barreEtat.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));

        labelConnexion.setText(" ");

        menuBar.setForeground(new java.awt.Color(0, 102, 255));
        menuBar.setFont(new java.awt.Font("Cambria", 0, 14));

        menuFichier.setForeground(new java.awt.Color(0, 153, 204));
        menuFichier.setText("Fichier");
        menuFichier.setFont(new java.awt.Font("Cambria", 0, 14));

        itemConnexion.setText("Se connecter");
        itemConnexion.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                itemConnexionActionPerformed(evt);
            }
        });
        menuFichier.add(itemConnexion);

        itemDeconnexion.setText("Se deconnecter");
        itemDeconnexion.setEnabled(false);
        itemDeconnexion.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                itemDeconnexionActionPerformed(evt);
            }
        });
        menuFichier.add(itemDeconnexion);

        menuBar.add(menuFichier);

        menuHelp.setForeground(new java.awt.Color(0, 153, 204));
        menuHelp.setText("A propos");
        menuHelp.setFont(new java.awt.Font("Cambria", 0, 14));
        menuHelp.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                aboutDialog(evt);
            }
        });
        menuBar.add(menuHelp);

        setJMenuBar(menuBar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(158, 158, 158)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(logField, javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(labelLogin, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(connectButton, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(192, Short.MAX_VALUE))
            .addComponent(barreEtat, javax.swing.GroupLayout.DEFAULT_SIZE, 445, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addGap(182, 182, 182)
                .addComponent(labelConnexion, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(212, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(143, 143, 143)
                .addComponent(labelLogin)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(logField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(connectButton)
                .addGap(40, 40, 40)
                .addComponent(labelConnexion)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 54, Short.MAX_VALUE)
                .addComponent(barreEtat, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    
    /**
     * Gère l'action sur le bouton "connect"
     * @param evt
     */
private void connectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectButtonActionPerformed
// TODO add your handling code here:
    connexion();    
}//GEN-LAST:event_connectButtonActionPerformed


    /**
    * Affiche la fenêtre "A propos" suite au click sur le bouton "A propos"
    * du menu
    * @param evt Evénement click sur l'onglet "A propos"
    */
private void aboutDialog(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_aboutDialog

    String appName ="JChat Insa\n";
    String appVersion = "v1.1";
    String appBuild = "Decembre 2013";
    dialog = new AboutDialog(this,appName,appVersion,appBuild);
    dialog.setVisible(true);
}//GEN-LAST:event_aboutDialog


    /**
     * Gère la connexion de l'utilisateur local via l'appui sur la touche Entrée
     * @param evt
     */
private void logFieldKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_logFieldKeyPressed

    if (evt.getKeyCode()==KeyEvent.VK_ENTER)
        connexion();
}//GEN-LAST:event_logFieldKeyPressed


    /**
     * Gère la connexion de l'utilisateur local via l'onglet "Fichier" et le bouton "se conencter"
     * @param evt
     */
private void itemConnexionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_itemConnexionActionPerformed
// TODO add your handling code here:
      connexion();
}//GEN-LAST:event_itemConnexionActionPerformed

    private void itemDeconnexionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_itemDeconnexionActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_itemDeconnexionActionPerformed



    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel barreEtat;
    private javax.swing.JButton connectButton;
    private javax.swing.JMenuItem itemConnexion;
    private javax.swing.JMenuItem itemDeconnexion;
    private javax.swing.JLabel labelConnexion;
    private javax.swing.JLabel labelLogin;
    private javax.swing.JTextField logField;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JMenu menuFichier;
    private javax.swing.JMenu menuHelp;
    // End of variables declaration//GEN-END:variables
     
    private AboutDialog dialog ;
 
    

 }
